package top.korori.security;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import top.korori.common.enums.StatusCode;
import top.korori.common.model.Result;
import top.korori.common.utils.JwtUtils;
import top.korori.common.utils.RedisCache;
import top.korori.common.utils.ServletUtils;
import top.korori.system.annotation.PreAuth;
import top.korori.system.constant.Constant;
import top.korori.system.constant.RedisConstant;
import top.korori.system.entity.SysUser;
import top.korori.system.entity.model.LoginUser;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 登录权限拦截器
 */
@Component
public class SysAuthInterceptor implements HandlerInterceptor {

    @Value("${token.secret}")
    public String secret;

    @Value("${token.expireTime}")
    public Long expireTime;

    @Autowired
    private RedisCache redisCache;


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {

        String token = request.getHeader(Constant.HEADER);
        String jwtToken = StrUtil.replace(token, Constant.TOKEN_PREFIX, "");

        DecodedJWT decodedJWT = JwtUtils.verify(jwtToken,secret);

            if (ObjectUtil.isNull(decodedJWT)) {
                ServletUtils.renderString(response,JSON.toJSONString(Result.fail(StatusCode.APPROVE_FAIL)));
                return false;
            }

            String key = RedisConstant.SYS_USER_INFO + decodedJWT.getClaim(Constant.JWT_UID).asLong();
            LoginUser<SysUser> loginUser =  redisCache.get(key);

            if (ObjectUtil.isNull(loginUser)) {
                ServletUtils.renderString(response,JSON.toJSONString(Result.fail(StatusCode.APPROVE_FAIL)));
                return false;
            }

            String loginTime = loginUser.getTime();
            String jwtTime = decodedJWT.getClaim(Constant.JWT_TIME).asString();

            if (!StrUtil.equals(loginTime,jwtTime)) {
                ServletUtils.renderString(response,JSON.toJSONString(Result.fail(StatusCode.APPROVE_FAIL)));
                return false;
            }

            //刷新令牌剩余时间
            redisCache.expire(key,expireTime, TimeUnit.MINUTES);

        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        //权限校验
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        PreAuth preAuthorize = handlerMethod.getMethod().getAnnotation(PreAuth.class);
        if (ObjectUtil.isNull(preAuthorize)) return true;
        String value = preAuthorize.value();
        Set<String> perms = loginUser.getPerms();
        //如果有权限或者是id为1的超级管理员用户就放行
        if (perms.contains(value) || ObjectUtil.equal(loginUser.getUserId(), 1L)) {
            return true;
        }
        ServletUtils.renderString(response, JSON.toJSONString(Result.fail(StatusCode.AUTHORIZED)));
        return false;
    }
}
